package com.cheryl.springailearn.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.messages.Media;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.model.Generation;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RequestMapping("/chat/model")
@RequiredArgsConstructor
@RestController
public class ChatModelController {
    private final ChatModel chatModel;

    @GetMapping
    public String chat(@RequestParam("msg")String msg) {
        return chatModel.call(msg);
    }

    /**
     * Spring AI 支持 OpenAI 的 AI 语言模型 ChatGPT
     * @param msg
     * @return
     */
    @GetMapping("/openai")
    public String openai(@RequestParam("msg")String msg) {
        ChatResponse call = chatModel.call(
                new Prompt(
                        msg,
                        OpenAiChatOptions.builder()//可以更换成其他大模型，如Anthropic3ChatOptions亚马逊
                                .withModel("gpt-3.5-turbo")
                                .withTemperature(0.8F)
                                .build()
                )
        );
        return call.getResult().getOutput().getContent();
    }
    /**
     * 流式响应
     * @param msg
     * @return
     */
    @GetMapping(value = "/openai/stream",produces="text/html;charset=UTF-8")
    public Flux<ChatResponse> stream(@RequestParam("msg")String msg) {
        return chatModel.stream(
                new Prompt(
                        msg,
                        OpenAiChatOptions.builder()//可以更换成其他大模型，如Anthropic3ChatOptions亚马逊
                                .withModel("gpt-3.5-turbo")
                                .withTemperature(0.8F)
                                .build()
                )
        );
    }
    /**
     * 多模态是指模型同时理解和处理来自各种来源的信息的能力，包括文本、图像、音频和其他数据格式。
     * 仅支持 chatGPT4.0
     * @param msg
     * @return
     */
    @GetMapping(value = "/openai/multimodal",produces="text/html;charset=UTF-8")
    public String multimodal(@RequestParam("msg")String msg) throws IOException {
        byte[] imageData = new ClassPathResource("/multimodal.test.png").getContentAsByteArray();
        var userMessage = new UserMessage(msg,
                List.of(new Media(
                        MimeTypeUtils.IMAGE_PNG,
                        new URL("https://docs.spring.io/spring-ai/reference/1.0-SNAPSHOT/_images/multimodal.test.png")
                )));

        ChatResponse response = chatModel.call(new Prompt(List.of(userMessage),
                OpenAiChatOptions.builder().withModel(OpenAiApi.ChatModel.GPT_4_O.getValue()).build()));

        return response.getResult().getOutput().getContent();
    }


    @GetMapping("/prompt")
    public String prompt(@RequestParam("name")String name,@RequestParam("voice")String voice){
        String userText= """
                给我推荐上海的至少三个旅游景点
                """;
        UserMessage userMessage = new UserMessage(userText);
        String systemText= """
                你是一个旅游咨询助手，可以帮助人们查询旅游信息。
                你的名字是{name},
                你应该用你的名字和{voice}的风格回复用户的请求。
                """;
        SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemText);
        Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", name, "voice", voice));
        Prompt prompt = new Prompt(List.of(userMessage, systemMessage));
        List<Generation> results = chatModel.call(prompt).getResults();
        return results.stream().map(x->x.getOutput().getContent()).collect(Collectors.joining(""));
    }
}
